package orm

import (
	"fmt"
	"playbook/ginsvr/src/global"
	"playbook/ginsvr/src/utils/uuidutil"

	"encoding/json"

	"github.com/sirupsen/logrus"
)

type Loop struct {
	Loopid                   string                 `json:"id"`
	Name                     string                 `json:"name"`
	Inputparammappingid      string                 `json:"-"`
	Inputparammapping        map[string]interface{} `gorm:"-" json:"input-parameter-mapping"`
	Outputparammappingid     string                 `json:"-"`
	Outputparammapping       map[string]interface{} `gorm:"-" json:"output-parameter-mapping"`
	Loopinputparammappingid  string                 `json:"-"`
	LoopInputparammapping    map[string]interface{} `gorm:"-" json:"loop-input-parameter-mapping"`
	Loopoutputparammappingid string                 `json:"-"`
	LoopOutputparammapping   map[string]interface{} `gorm:"-" json:"loop-output-parameter-mapping"`
	Inputparamid             string                 `json:"-"`
	Inputparameter           map[string]interface{} `gorm:"-" json:"input-parameter"`
	Outputparamid            string                 `json:"-"`
	Outputparameter          map[string]interface{} `gorm:"-" json:"output-parameter"`
	Servicebindingid         string                 `json:"-"`
	Servicebinding           Service                `gorm:"-" json:"service-binding"`
	Outputcontextid          string                 `json:"-"`
	Outputcontext            map[string]interface{} `gorm:"-" json:"output-context"`
	Overtime                 string                 `json:"overtime"`
	Transion                 []Transion             `gorm:"-" json:"transition"`
	Firsttransion            []Transion             `gorm:"-" json:"first-transition"`
	Activitiesid             string                 `json:"-"`
	Activities               map[string]interface{} `gorm:"-" json:"activities"`
	Type                     int                    `gorm:"-" json:"type"`
}

type Transion struct {
	Expre          map[string]interface{} `gorm:"-" json:"expression"`
	Expression     string                 `json:"-"`
	Activityid     string                 `json:"-"`
	Transionid     string                 `json:"-"`
	Nextactivityid string                 `json:"activityid"`
	Seq            string                 `json:"seq"`
	Isdeleted      int                    `json:"-"`
	Type           string                 `json:"-"`
}

func AddLoop(loop Loop, activitiesList *[]Activitys, msgbms *[]MsgParamMapping, mapps *[]Mapping, paramMap map[string]Parameter,
	paramRelas *[]Paramrelation, transionList *[]Transion, services *[]Service, activityList *[]Activity, processname string) string {

	inputparameter := loop.Inputparameter
	inputparameterid := ""
	if inputparameter != nil {
		if _, ok := inputparameter["parameter"]; ok {
			datanode := getParamDataNode(inputparameter["parameter"].(map[string]interface{}))
			if datanode != nil {
				inputparameterid = addParameter(datanode, paramMap, paramRelas)
			}
		}
	}

	outputparameter := loop.Outputparameter
	outputparameterid := ""
	if outputparameter != nil {

		if _, ok := outputparameter["parameter"]; ok {
			datanode := getParamDataNode(outputparameter["parameter"].(map[string]interface{}))
			if datanode != nil {
				outputparameterid = addParameter(datanode, paramMap, paramRelas)
			}
		}

	}

	genebeanmsgList = append(genebeanmsgList, GenebeanParammsg{
		Inparamid:  inputparameterid,
		Outparamid: outputparameterid,
		Subpath:    loop.Name,
	})

	servicebinding := loop.Servicebinding
	servicebindingid := ""
	if servicebinding != (Service{}) {
		servicebindingid = addService(servicebinding, services)
	}

	inputparammapping := loop.Inputparammapping
	inputparammappingid := ""
	if inputparammapping != nil {
		if _, ok := inputparammapping["massage-bean-mapping"]; ok {
			inputparammap := inputparammapping["massage-bean-mapping"].(map[string]interface{})
			if inputparammap["mapping"] != nil {
				inputmappings := getMappings(inputparammap["mapping"].([]interface{}))
				inputparammappingid = addMsgMapping(inputmappings, msgbms, mapps)
			}
		}
	}

	outputparammapping := loop.Outputparammapping
	outputparammappingid := ""
	if outputparammapping != nil {
		if _, ok := outputparammapping["massage-bean-mapping"]; ok {
			outputparammap := outputparammapping["massage-bean-mapping"].(map[string]interface{})
			if outputparammap["mapping"] != nil {
				outputmappings := getMappings(outputparammap["mapping"].([]interface{}))
				outputparammappingid = addMsgMapping(outputmappings, msgbms, mapps)
			}
		}
	}

	outputcontextid := ""
	outputcontext := loop.Outputcontext
	if outputcontext != nil {
		if _, ok := outputcontext["parameter"]; ok {
			outputcontextid = addParameter(outputcontext["parameter"].(map[string]interface{}), paramMap, paramRelas)
		}
	}

	loopInputparammapping := loop.LoopInputparammapping
	loopinputparammappingid := ""
	if loopInputparammapping != nil {
		if _, ok := loopInputparammapping["massage-bean-mapping"]; ok {
			inputparammap := inputparammapping["massage-bean-mapping"].(map[string]interface{})
			loopinputmappings := getMappings(inputparammap["mapping"].([]interface{}))
			loopinputparammappingid = addMsgMapping(loopinputmappings, msgbms, mapps)
		}
	}

	loopOutputparammapping := loop.LoopOutputparammapping
	loopOutputparammappingid := ""
	if loopOutputparammapping != nil {
		if _, ok := loopOutputparammapping["massage-bean-mapping"]; ok {
			outputparammap := inputparammapping["massage-bean-mapping"].(map[string]interface{})
			loopoutputmappings := getMappings(outputparammap["mapping"].([]interface{}))
			loopOutputparammappingid = addMsgMapping(loopoutputmappings, msgbms, mapps)
		}
	}

	activitiesId := ""
	if loop.Activities != nil {
		if _, ok := loop.Activities["activity"]; ok {
			activitiesId = addActivities(loop.Activities["activity"].([]interface{}), activitiesList, msgbms, mapps, paramMap, paramRelas, transionList, services, activityList, processname)
		}
	}

	loopid := loop.Loopid
	err := db.Exec("INSERT INTO loop(name, loopid, inputparamid, outputparamid, inputparammappingid,outputparammappingid,servicebindingid, outputcontextid, overtime, activitiesid, loopinputparammappingid,loopoutputparammappingid)	VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12)",
		loop.Name, loopid, inputparameterid, outputparameterid, inputparammappingid, outputparammappingid, servicebindingid, outputcontextid, loop.Overtime, activitiesId, loopinputparammappingid, loopOutputparammappingid)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err":    err,
			"loopid": loopid,
		}).Error("add mapping err.")
		return ""
	}

	if loop.Transion != nil {
		addTransion(loopid, loop.Transion, "0", transionList)
	}

	if loop.Firsttransion != nil {
		addTransion(loopid, loop.Firsttransion, "1", transionList)
	}

	return loopid
}

func getMappings(inputparammap []interface{}) []Mapping {
	var res []Mapping
	for i, _ := range inputparammap {
		resByre, resByteErr := json.Marshal(inputparammap[i].(map[string]interface{}))
		if resByteErr != nil {
			fmt.Printf("%v", resByteErr)
		}
		var mapping Mapping
		jsonRes := json.Unmarshal(resByre, &mapping)
		if jsonRes != nil {
			fmt.Printf("%v", jsonRes)
		}
		res = append(res, mapping)
	}
	return res
}

func addTransion(activityid string, transions []Transion, types string, transionList *[]Transion) string {

	var transionid string

	for _, transion := range transions {
		transionid = uuidutil.GetUUID()
		bytes, _ := json.Marshal(transion.Expre)
		expre := string(bytes)

		*transionList = append(*transionList, Transion{
			Expression:     expre,
			Activityid:     activityid,
			Transionid:     transionid,
			Nextactivityid: transion.Nextactivityid,
			Seq:            transion.Seq,
			Type:           types,
		})
	}
	return "ok"
}

func GetLoop(loopid string) Loop {
	var loop Loop

	db.Table("loop").Where("loopid = ?", loopid).Find(&loop)
	loop.Inputparameter = map[string]interface{}{"parameter": getParameter(loop.Inputparamid, "")}
	loop.Outputparameter = map[string]interface{}{"parameter": getParameter(loop.Outputparamid, "")}
	loop.Outputcontext = map[string]interface{}{"parameter": getParameter(loop.Outputcontextid, "")}

	loop.LoopInputparammapping = map[string]interface{}{"massage-bean-mapping": getMsgMapping(loop.Loopinputparammappingid)}
	loop.LoopOutputparammapping = map[string]interface{}{"massage-bean-mapping": getMsgMapping(loop.Loopoutputparammappingid)}
	loop.Inputparammapping = map[string]interface{}{"massage-bean-mapping": getMsgMapping(loop.Inputparammappingid)}
	loop.Outputparammapping = map[string]interface{}{"massage-bean-mapping": getMsgMapping(loop.Outputparammappingid)}

	loop.Servicebinding = getService(loop.Servicebindingid)

	loop.Activities = map[string]interface{}{"activity": getActivities(loop.Activitiesid)}

	loop.Transion = getTransion(loop.Loopid, "0")
	loop.Firsttransion = getTransion(loop.Loopid, "1")
	loop.Type = 1
	return loop
}

func getTransion(activityid string, types string) []Transion {
	var trans []Transion

	db.Table("transion").Where("activityid = ? and type = ? and isdeleted = 0", activityid, types).Order("seq").Find(&trans)

	//返回没有删除的transion
	for i, _ := range trans {
		var tempMap map[string]interface{}
		json.Unmarshal([]byte(trans[i].Expression), &tempMap)
		trans[i].Expre = tempMap
	}
	return trans
}

//将activityid的全部transion逻辑删除
func updateTransion(activityid string, types string) Response {
	var resp Response
	err := db.Exec("update transion set isdeleted = 1 where activityid= $1 and type = $2", activityid, types)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err":        err,
			"activityid": activityid,
		}).Error("update transion err.")
		resp.RespCode = "000001"
		resp.RespMsg = err.Error.Error()
		return resp
	}
	resp.RespCode = "000000"
	return resp
}

func SaveParams(params []Parameter) error {
	err := db.Table("parameter").CreateInBatches(params, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("saveParams err.")
	}
	return err.Error

}

func SaveParamDefines(params []map[string]interface{}) error {
	err := db.Table("paramdefine").CreateInBatches(params, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("saveParams err.")
	}
	return err.Error

}

func SaveAsvs(asvs []Service) error {
	err := db.Table("service").CreateInBatches(asvs, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("SaveAsvs err.")
	}
	return err.Error

}

func SaveActivies(actis []AtomSvrDefine) error {
	err := db.Table("atomsvrdefine").CreateInBatches(actis, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("SaveActivies err.")
	}
	return err.Error

}

func UpdateActivies(actis []AtomSvrDefine) error {
	tx := db.Begin()
	var err error
	for _, atomSvrDefine := range actis {
		var count int64
		var asdid string
		err = tx.Table("atomsvrdefine").Select("atomsvrid").Where("asname = ?", atomSvrDefine.Asname).Find(&asdid).Count(&count).Error
		if err != nil {
			tx.Rollback()
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("UpdateActivies err, select error")
			return err
		}
		if count == 0 {
			err = tx.Table("atomsvrdefine").CreateInBatches(atomSvrDefine, 1).Error
			if err != nil {
				tx.Rollback()
				global.LOG.WithFields(logrus.Fields{
					"err": err,
				}).Error("UpdateActivies err, create error")
				return err
			}
		} else {
			atomSvrDefine.Atomsvrid = asdid
			err = tx.Table("atomsvrdefine").Where("asname = ?", atomSvrDefine.Asname).Updates(atomSvrDefine).Error
			if err != nil {
				tx.Rollback()
				global.LOG.WithFields(logrus.Fields{
					"err": err,
				}).Error("UpdateActivies err, update error")
				return err
			}
		}
	}
	tx.Commit()
	return nil
}

func SaveParamRelas(relas []Paramrelation) error {
	err := db.Table("paramrelation").CreateInBatches(relas, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("SaveParamRelas err.")
	}
	return err.Error

}

func saveMsgBeanMappings(msgs []MsgParamMapping) error {

	err := db.Table("massagebeanmapping").CreateInBatches(msgs, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("saveMsgBeanMappings err.")
	}
	return err.Error

}

func saveMappings(mappings []Mapping) error {

	err := db.Table("mapping").CreateInBatches(mappings, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("saveMappings err.")
	}
	return err.Error
}

func SaveActivitys(activitys []Activitys) error {

	err := db.Table("activities").CreateInBatches(activitys, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("saveActivitys err.")
	}
	return err.Error
}

func SaveTransions(trans []Transion) error {

	err := db.Table("transion").CreateInBatches(trans, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("saveTransions err.")
	}
	return err.Error
}
func SaveActivityList(actis []Activity) error {

	err := db.Table("activity").CreateInBatches(actis, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("saveActivityList err.")
	}
	return err.Error
}
